package tech.xs.common.auth.util;

import cn.hutool.core.util.IdUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.xs.common.auth.domain.cache.AuthTokenCache;
import tech.xs.common.framework.domain.constant.Symbol;
import tech.xs.common.auth.domain.enums.AuthClientTypeEnum;
import tech.xs.common.framework.holder.SpringContextHolder;
import tech.xs.common.framework.util.AuthHeaderUtil;

import java.time.Duration;

/**
 * Token工具
 *
 * @author 沈家文
 * @since 2023/7/26 11:31
 */
public class AuthTokenUtil {

    private static final Logger log = LoggerFactory.getLogger(AuthHeaderUtil.class);

    private static final String CACHE_TOKEN_KEY = "auth:token:";

    public static String getTokenCacheKey(Long userId, AuthClientTypeEnum clientType) {
        return CACHE_TOKEN_KEY + userId + Symbol.COLON_STR + clientType.getValue();
    }

    public static String createTokenStr(Long userId, AuthClientTypeEnum clientType) {
        log.debug("创建token userId:" + userId + " clientType:" + clientType);
        String token = userId + Symbol.HYPHEN_STR + clientType.getValue() + Symbol.HYPHEN_STR + IdUtil.simpleUUID();
        return token + DigestUtils.md5Hex(token);
    }

    public static AuthTokenCache getToken() {
        AuthHeaderUtil.AuthHeader authHeader = AuthHeaderUtil.getAuthHeader();
        return getToken(authHeader.getUserId(), authHeader.getClientType());
    }

    public static AuthTokenCache getToken(Long userId, AuthClientTypeEnum clientType) {
        RedissonClient redissonClient = SpringContextHolder.getBean(RedissonClient.class);
        return getToken(redissonClient, userId, clientType);
    }

    public static AuthTokenCache getToken(RedissonClient redissonClient, Long userId, AuthClientTypeEnum clientType) {
        RBucket<AuthTokenCache> bucket = redissonClient.getBucket(AuthTokenUtil.getTokenCacheKey(userId, clientType));
        return bucket.get();
    }

    public static void refreshAuthToken(RedissonClient redissonClient, AuthTokenCache token) {
        AuthClientTypeEnum clientType = token.getClientType();
        switch (clientType) {
            case BROWSER:
            case APP:
            case UNKNOWN: {
                if (token.getAccessTokenInvalidTime() - System.currentTimeMillis() < clientType.getAccessTokenRefreshInterval()) {
                    return;
                }
                token.setAccessTokenInvalidTime(System.currentTimeMillis() + clientType.getAccessTokenValidity());
                RBucket<AuthTokenCache> bucket = redissonClient.getBucket(AuthTokenUtil.getTokenCacheKey(token.getUserId(), clientType));
                bucket.set(token, Duration.ofMillis(clientType.getAccessTokenValidity()));
                return;
            }
            default: {
                return;
            }
        }
    }


}
